#pragma once

#include  <cstring>
#include "Type.h"
#include "PropertyList.h"
#include "TypeInstance.h"
#include "Property.h"

class RObject;
class CProperty;


class WHENGINE_API CNativeStrut : public CType
{
public:	
	CNativeStrut(CString InFullName,std::function<void()> InPostConstructFunction);

};


template<typename RStructType>
class  TStruct :public CNativeStrut
{
public:
	TStruct(CString InFullName,std::function<void()> InPostConstructFunction)
		:CNativeStrut(InFullName,InPostConstructFunction) 
	{
		Instancable=new CStructInstance(this);
	}

protected:
	class CStructInstance : public ITypeInstance
	{
	protected:
		CNativeStrut* Type;
	public:
		CStructInstance(CNativeStrut* InType)
		{
			Type=InType;
		}

		virtual uint32_t GetSize() override
		{
			return sizeof(RStructType);
		}



		uint64_t GetInstanceHash(const void *InInstance) const override
		{
			if(!Type->Properties)
			{
				return 0;
			}

			return Type->Properties->GetNonStaticFieldHash(InInstance);
		}

		bool IsInstanceEqual(const void *A, const void *B) const override
		{
			//compare whole memory
			return std::memcmp(A,B,Type->GetSize())==0;
		}


		void InitInstance(void * InMemory) override
		{
			new (InMemory) RStructType();
		}

		void EraseInstance(void * Instance) override
		{
			reinterpret_cast<RStructType*>(Instance)->~RStructType();
		}

		void CloneInstance(const void * Instance, void * Memory) override
		{
			new (Memory) RStructType(*reinterpret_cast<const RStructType*>(Instance));
		}
	
		void* CreateInstance() override
		{
			return new RStructType();
		}

		void ResetAllocated(void* InMemory) override
		{
			//1. call destructor
			RStructType* Instance= reinterpret_cast<RStructType*>(InMemory);
			Instance->~RStructType();
			//2. call constructor
			new (Instance) RStructType();
		}

		CString ToDebugString(const void * InInstance) const override
		{
    		return Type->GetFullName()+U"//"+CString::CreateHex((uint64_t)InInstance,true);
		}

		virtual int64_t GetDebugNamedChildNum(const void * Instance) const override
		{ 
			return Type->Properties->GetNonStaticFieldProperties().Num();
		}

		virtual CString GetDebugNamedChildName(int64_t Index,const void * Instance) const override
		{ 
			return Type->Properties->GetNonStaticFieldProperties()[Index]->GetName();
		}

		virtual CType* GetDebugNamedChildType(int64_t Index,const void * Instance) const override
		{ 
			return Type->Properties->GetNonStaticFieldProperties()[Index]->GetType().BasicType;
		}
		
		virtual const void* GetDebugNamedChildValue(int64_t Index,const void * Instance) const override
		{ 
			return Type->Properties->GetNonStaticFieldProperties()[Index]->FieldProperty->GetValuePointer(Instance);
		}

	
	};
}; 


namespace WH
{
	template<typename T>
	concept IsReflectableStruct= requires ()
	{
		{ T::StaticStruct() }->std::same_as<CNativeStrut*>;
	};



};
